package com.cskaoyan.wordmemorize.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLog;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLogConstant;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.EmployeeConverter;
import com.cskaoyan.wordmemorize.dao.entity.EmployeeDO;
import com.cskaoyan.wordmemorize.dao.entity.EmployeeRoleDO;
import com.cskaoyan.wordmemorize.dao.entity.RoleDO;
import com.cskaoyan.wordmemorize.dao.mapper.EmployeeMapper;
import com.cskaoyan.wordmemorize.dao.mapper.EmployeeRoleMapper;
import com.cskaoyan.wordmemorize.dao.mapper.RoleMapper;
import com.cskaoyan.wordmemorize.dto.admin.DeleteEmployeeRoleOperateDTO;
import com.cskaoyan.wordmemorize.dto.admin.EmployeeDTO;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.request.EmployeeCommand;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.cskaoyan.wordmemorize.common.aspect.operate.OperateLogConstant.OPERATE_ADD;

@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, EmployeeDO> implements EmployeeService {


    @Autowired
    EmployeeMapper employeeMapper;

    @Autowired
    EmployeeConverter employeeConverter;

    @Autowired
    EmployeeRoleMapper employeeRoleMapper;

    @Autowired
    RoleMapper roleMapper;

    @Override
    public EmployeeDTO login(String userName, String password) {

        // 1. 将明文密码变为密文密码
        String encodePassword = SaSecureUtil.md5(password);

        // 2.根据用户名和密码查询数据库
        LambdaQueryWrapper<EmployeeDO> employeeWrapper = new LambdaQueryWrapper<>();
        employeeWrapper.eq(EmployeeDO::getName,userName)
                .eq(EmployeeDO::getPassword,encodePassword);

        EmployeeDO employeeDO = employeeMapper.selectOne(employeeWrapper);
        if (employeeDO == null) {
            throw new BusinessException(ResultCodeEnum.LOCAL_LOGIN_FAIL);
        }else {
            return employeeConverter.employeeDO2DTO(employeeDO);
        }
    }

    @Override
    public EmployeeDTO getEmployeeInfo(Long employeeId) {
        // 返回的password应该为null，在xml中应设置
        EmployeeDO employeeDo = employeeMapper.getEmployeeInfo(employeeId);
        EmployeeDTO employeeDTO = employeeConverter.employeeDO2DTO(employeeDo);
        return employeeDTO;
    }

    @Override
    public PageDTO<EmployeeDTO> getEmployeePage(PageRequest request) {
        // 返回的password应该为null！！！
        if (request.getPageNum() == null){
            List<EmployeeDO> employeeDOS = employeeMapper.selectList(null);
            employeeDOS.forEach(a-> a.setPassword(null));
            PageDTO<EmployeeDTO> pageDTO = employeeConverter.emoloyeePage2PageDTO(employeeDOS, (long) employeeDOS.size());
            return pageDTO;
        }
        Page<EmployeeDO> page = new Page<>(request.getPageNum(), request.getCount());
        LambdaQueryWrapper<EmployeeDO> queryWrapper = new LambdaQueryWrapper<>();
        if (request.getKeyword() != null){
            queryWrapper.like(EmployeeDO::getName, request.getKeyword())
                    .or()
                    .like(EmployeeDO::getNickName, request.getKeyword());
        }
        Page<EmployeeDO> selectPage = employeeMapper.selectPage(page, queryWrapper);
        List<EmployeeDO> employeeDOS = selectPage.getRecords();
        employeeDOS.forEach(a->{
            a.setPassword(null);
            Long id = a.getId();
            LambdaQueryWrapper<EmployeeRoleDO> roleQueryWrapper = new LambdaQueryWrapper<>();
            roleQueryWrapper.eq(EmployeeRoleDO::getEmployeeId, id);
            List<EmployeeRoleDO> employeeRoleDOS = employeeRoleMapper.selectList(roleQueryWrapper);
            List<Long> roleList = employeeRoleDOS.stream()
                    .map(EmployeeRoleDO::getRoleId)
                    .collect(Collectors.toList());
            a.setRoleIds(roleList);
        });
        List<EmployeeDO> totalEmployee = employeeMapper.selectList(queryWrapper);
        PageDTO<EmployeeDTO> pageDTO = employeeConverter.emoloyeePage2PageDTO(employeeDOS, (long) totalEmployee.size());
        return pageDTO;
    }

    @Override
    public void addEmployee(EmployeeCommand command) {
        EmployeeDO employeeDO = employeeConverter.command2EmployeeDO(command);
        LambdaQueryWrapper<EmployeeDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmployeeDO::getName, employeeDO.getName());
        List<EmployeeDO> employeeDOS = employeeMapper.selectList(queryWrapper);
        if (employeeDOS !=null && employeeDOS.size()>0 ){
            throw new BusinessException("当前员工姓名已存在，请重新添加员工！", 500);
        }
        String password = employeeDO.getPassword();
        if (password == null || password.length()<6){
            throw new BusinessException("密码长度不能少于6位！", 500);
        }
        String md5Password = SaSecureUtil.md5(password);
        employeeDO.setPassword(md5Password);
        employeeMapper.insert(employeeDO);

        // 在employee_role表中插入 employee 与 role 的关系
        List<Long> roleIds = employeeDO.getRoleIds();
        if (roleIds != null && !roleIds.isEmpty()){
            roleIds.forEach(a->{
                EmployeeRoleDO employeeRoleDO = new EmployeeRoleDO();
                employeeRoleDO.setEmployeeId(employeeDO.getId());
                employeeRoleDO.setRoleId(a);
                employeeRoleMapper.insert(employeeRoleDO);
            });
        }
    }

    @Override
    public void updateEmployee(EmployeeCommand command) {
        EmployeeDO employeeDO = employeeConverter.command2EmployeeDO(command);
        LambdaQueryWrapper<EmployeeDO> preQueryWrapper = new LambdaQueryWrapper<>();
        preQueryWrapper.eq(EmployeeDO::getName, employeeDO.getName());
        EmployeeDO selectOne = employeeMapper.selectOne(preQueryWrapper);
        EmployeeDO sourceOne = employeeMapper.selectById(employeeDO.getId());
        if (!sourceOne.getName().equals(employeeDO.getName()) && selectOne != null ){
            throw new BusinessException("当前姓名已存在，请重新编辑！", 500);
        }
        
        String password = employeeDO.getPassword();
        if (password != null && password.length()<6){
            throw new BusinessException("密码长度不能少于6位！", 500);
        }
        if (password != null){
            String md5Password = SaSecureUtil.md5(password);
            employeeDO.setPassword(md5Password);
        }
        employeeMapper.updateById(employeeDO);

        List<Long> roleIds = employeeDO.getRoleIds();
        if (roleIds != null && !roleIds.isEmpty()){
            roleIds.forEach(a->{
                LambdaQueryWrapper<EmployeeRoleDO> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(EmployeeRoleDO::getEmployeeId, employeeDO.getId())
                        .eq(EmployeeRoleDO::getRoleId, a);
                List<EmployeeRoleDO> employeeRoleDOS = employeeRoleMapper.selectList(queryWrapper);
                if (employeeRoleDOS.isEmpty()){
                    EmployeeRoleDO employeeRoleDO = new EmployeeRoleDO();
                    employeeRoleDO.setEmployeeId(employeeDO.getId());
                    employeeRoleDO.setRoleId(a);
                    employeeRoleMapper.insert(employeeRoleDO);
                }
            });
        }
    }

    @Transactional
    @Override
    public void delete(Long employeeId) {
        int i = employeeMapper.deleteById(employeeId);
        if (i == 0){
            throw new BusinessException("employeeId:"+employeeId+"不存在", 500);
        }
        LambdaQueryWrapper<EmployeeRoleDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmployeeRoleDO::getEmployeeId, employeeId);
        employeeRoleMapper.delete(queryWrapper);
    }

    @Override
    public DeleteEmployeeRoleOperateDTO deleteRole(Long employeeId, Long roleId) {
        LambdaQueryWrapper<EmployeeRoleDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmployeeRoleDO::getEmployeeId, employeeId)
                .eq(EmployeeRoleDO::getRoleId, roleId);
        employeeRoleMapper.delete(queryWrapper);

        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        RoleDO roleDO = roleMapper.selectById(roleId);
        DeleteEmployeeRoleOperateDTO deleteEmployeeRoleOperateDTO = new DeleteEmployeeRoleOperateDTO();
        deleteEmployeeRoleOperateDTO.setEmployeeId(employeeId);
        deleteEmployeeRoleOperateDTO.setRoleId(roleId.toString());
        deleteEmployeeRoleOperateDTO.setEmployeeName(employeeDO.getName());
        deleteEmployeeRoleOperateDTO.setRoleName(roleDO.getName());
        return deleteEmployeeRoleOperateDTO;
    }

    @Override
    public void updateLoginInfo(Long employeeId, String ip, LocalDateTime time) {

        EmployeeDO employeeDO = new EmployeeDO();
        employeeDO.setId(employeeId);
        employeeDO.setLastLoginIp(ip);
        employeeDO.setLastLoginTime(time);

        employeeMapper.updateById(employeeDO);
    }

    @Override
    public Set<String> getPermissionAlias(Long employeeId) {
        // 使用set，而不是直接用list接收的好处：去重
        Set<String> permissionAlias = employeeMapper.getPermissionAlias(employeeId);
        return permissionAlias;
    }
}
